﻿namespace Hotel.Module.Resources
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Hotel.Module.Infrastructure;
    using Hotel.Model.Infrastructure;
    using System.Configuration;
    using System.IO;
    using ResourcesModels = Hotel.Module.Resources.Models;
    using Entities = Hotel.Module.Resources.DataRepository;
    internal class HotelResourcesRepository : IStorageController
    {
        /// <summary>
        /// Add table entity to current list
        /// </summary>
        /// <typeparam name="T">Type of entity to add</typeparam>
        /// <param name="tableEntity">Table entity</param>
        public void Add<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ResourcesModels.Room)
            {
                ResourcesModels.Room item = tableEntity as ResourcesModels.Room;
                Entities.Room result = new Entities.Room();
                item.AssignTo(result);
                EntityStorage.Rooms.AddObject(result);
                return;
            }
            if (tableEntity is ResourcesModels.Hall)
            {
                ResourcesModels.Hall item = tableEntity as ResourcesModels.Hall;
                Entities.Hall result = new Entities.Hall();
                item.AssignTo(result);
                EntityStorage.AddToHalls(result);
                return;
            }
            if (tableEntity is ResourcesModels.Service)
            {
                ResourcesModels.Service item = tableEntity as ResourcesModels.Service;
                Entities.Service result = new Entities.Service();
                item.AssignTo(result);
                EntityStorage.AddToServices(result);
                return;
            }
            throw new NotSupportedException();
        }

        /// <summary>
        /// Update info in current list
        /// </summary> 
        /// <typeparam name="T">Type of entity to update</typeparam>
        /// <param name="tableEntity">Table entity</param>
        public void Update<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ResourcesModels.Room)
            {
                ResourcesModels.Room item = tableEntity as ResourcesModels.Room;
                foreach (var entityRoom in EntityStorage.Rooms)
                {
                    if (entityRoom.Number == item.Number)
                    {
                        item.AssignTo(entityRoom);
                        break;
                    }
                }
                return;
            }

            if (tableEntity is ResourcesModels.Hall)
            {
                ResourcesModels.Hall item = tableEntity as ResourcesModels.Hall;
                foreach (var entityHall in EntityStorage.Halls)
                {
                    if (entityHall.Number == item.Number)
                    {
                        item.AssignTo(entityHall);
                        break;
                    }
                }
                return;
            }

            if (tableEntity is ResourcesModels.Service)
            {
                ResourcesModels.Service item = tableEntity as ResourcesModels.Service;
                foreach (var entityService in EntityStorage.Services)
                {
                    if (entityService.Id == item.ID)
                    {
                        item.AssignTo(entityService);
                        break;
                    }
                }
                return;
            }
            throw new NotSupportedException();
        }

        /// <summary>
        /// Remove entity from current list
        /// </summary> 
        /// <typeparam name="T">Type of entity to remove</typeparam>
        /// <param name="tableEntity">Table entity</param>
        public void Delete<T>(T tableEntity) where T : Model.Infrastructure.IDistributedStorageEntity
        {
            if (tableEntity is ResourcesModels.Room)
            {
                ResourcesModels.Room item = tableEntity as ResourcesModels.Room;

                Entities.Room result = null;
                foreach (var entityRoom in EntityStorage.Rooms)
                {
                    if (entityRoom.Number == item.Number)
                    {
                        result = entityRoom;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            if (tableEntity is ResourcesModels.Hall)
            {
                ResourcesModels.Hall item = tableEntity as ResourcesModels.Hall;

                Entities.Hall result = null;
                foreach (var entityHall in EntityStorage.Halls)
                {
                    if (entityHall.Number == item.Number)
                    {
                        result = entityHall;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            if (tableEntity is ResourcesModels.Service)
            {
                ResourcesModels.Service item = tableEntity as ResourcesModels.Service;

                Entities.Service result = null;
                foreach (var entityService in EntityStorage.Services)
                {
                    if (entityService.Id == item.ID)
                    {
                        result = entityService;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            if (tableEntity is ResourcesModels.Period)
            {
                ResourcesModels.Period item = tableEntity as ResourcesModels.Period;

                Entities.Period result = null;
                foreach (var entityPeriod in EntityStorage.Periods)
                {
                    if (entityPeriod.OrderID == item.OrderID)
                    {
                        result = entityPeriod;
                        break;
                    }
                }
                if (result != null)
                {
                    EntityStorage.DeleteObject(result);
                }
                return;
            }

            throw new NotSupportedException();
        }

        /// <summary>
        /// Find method using Predicate
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public T Find<T>(Predicate<T> match)
        {
            if (typeof(T) == typeof(Models.Room))
            {
                foreach (var item in EntityStorage.Rooms)
                {
                    object result = Models.Room.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Hall))
            {
                foreach (var item in EntityStorage.Halls)
                {
                    object result = Models.Hall.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Period))
            {
                foreach (var item in EntityStorage.Periods)
                {
                    object result = Models.Period.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Service))
            {
                foreach (var item in EntityStorage.Services)
                {
                    object result = Models.Service.FromEnityModel(item);
                    if (match((T)result))
                        return (T)result;
                }
            }

            return default(T);
        }

        /// <summary>
        /// Get query of specified type
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IQueryable<T> GetQuery<T>() where T : IDistributedStorageEntity
        {
            if (typeof(T) == typeof(Models.Room))
            {
                var collection = from item in EntityStorage.Rooms select item;
                List<Models.Room> TCollection = new List<Models.Room>();
                foreach (var item in collection)
                {
                    TCollection.Add(ResourcesModels.Room.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            if (typeof(T) == typeof(Models.Hall))
            {
                var collection = from item in EntityStorage.Halls select item;
                List<Models.Hall> TCollection = new List<Models.Hall>();
                foreach (var item in collection)
                {
                    TCollection.Add(ResourcesModels.Hall.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            if (typeof(T) == typeof(Models.Service))
            {
                var collection = from item in EntityStorage.Services select item;
                List<Models.Service> TCollection = new List<Models.Service>();
                foreach (var item in collection)
                {
                    TCollection.Add(ResourcesModels.Service.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            if (typeof(T) == typeof(Models.Period))
            {
                var collection = from item in EntityStorage.Periods select item;
                List<Models.Period> TCollection = new List<Models.Period>();
                foreach (var item in collection)
                {
                    TCollection.Add(ResourcesModels.Period.FromEnityModel(item));
                }
                return (IQueryable<T>)TCollection.AsQueryable();
            }

            return default(IQueryable<T>);
        }

        /// <summary>
        /// Gets Emumerable collection of type T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IEnumerable<T> Enumerate<T>() where T : IDistributedStorageEntity
        {
            if (typeof(T) == typeof(Models.Room))
            {
                var collection = from item in EntityStorage.Rooms select item;
                foreach (var item in collection)
                {
                    object result = ResourcesModels.Room.FromEnityModel(item);
                    yield return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Hall))
            {
                var collection = from item in EntityStorage.Halls select item;
                foreach (var item in collection)
                {
                    object result = ResourcesModels.Hall.FromEnityModel(item);
                    yield return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Period))
            {
                var collection = from item in EntityStorage.Periods select item;
                foreach (var item in collection)
                {
                    object result = ResourcesModels.Period.FromEnityModel(item);
                    yield return (T)result;
                }
            }

            if (typeof(T) == typeof(Models.Service))
            {
                var collection = from item in EntityStorage.Services select item;
                foreach (var item in collection)
                {
                    object result = ResourcesModels.Service.FromEnityModel(item);
                    yield return (T)result;
                }
            }
        }

        #region Disposing

        ~HotelResourcesRepository()
        {
            Dispose(false);
        }

        private bool disposed = false;
        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    //Dispose managed resources
                }
                disposed = true;
            }
        }

        /// <summary>
        /// Disposing
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        public void SaveChanges()
        {
            EntityStorage.SaveChanges();
        }

        private readonly Entities.ResourceEntityModelContainer EntityStorage = new Entities.ResourceEntityModelContainer();
    }
}
